home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr48
/
st4gw110.zip
/
STUB4GW.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-12-29
|
10KB
|
524 lines
;
; Name: Stub Loader for DOS4GW DOS Extender
; Version: 1.10
; Date: Dec-29-1994
; Author: Vladimir Arnost (QA-Software) <xarnos00@dcse.fee.vutbr.cz>
; Compiler: TASM 3.2
;
; History:
; 1.00 Dec-20-1994 Written
; 1.10 Dec-29-1994 Minor changes, model changed from small to tiny
; Added quiet extender support
; Fixed bug in PrepareParams
.8086
.MODEL TINY, C
LOCALS
JUMPS
StackSize EQU 128
CRLF EQU 0Dh,0Ah
EOL EQU '$'
Environment EQU 2Ch
FCB1 EQU 5Ch
FCB2 EQU 6Ch
PSP_PARAMS EQU 80h
OFST EQU (WORD PTR 0)
SEGM EQU (WORD PTR 2)
.CODE
IFDEF QUIET
db 'DOS/4GW STUB V1.10Q - Copyright 1994 QA-Software'
ELSE
db 'DOS/4GW STUB V1.10 - Copyright 1994 QA-Software',0
ENDIF
;*** Main program
Stub4GW PROC FAR
mov dx,cs
mov ds,dx
; CS - code segment
; DS - data segment (same as CS in Tiny model)
; ES - PSP segment
call Check386
jnc @@1
mov dx,offset Msg_Need386
mov al,0FFh
jmp @@Error
.386
@@1: mov ax,es
mov fs,ax
mov gs,es:[Environment] ; environment segment
mov es,dx
; ES - data segment
; FS - PSP segment
; GS - environment segment
call ReleaseMemory
call FindDOS4GW
; DS:DX - DOS4GW path
call PrepareParams
; ES:BX - parameters
IFDEF QUIET
call PrepareEnvironment
ELSE
xor ax,ax
ENDIF
; AX - environment segment
call Exec
.8086
or ax,ax
jnz @@ExecError
; Get program exit code
mov ah,4Dh
int 21h
; AL=exit code
mov ah,4Ch
int 21h ; terminate
@@ExecError: mov bx,offset Msg_ErrorCode
call HexWord
mov dx,offset Msg_Error
mov al,0FEh
; In: DS:DX error message
; AL return code
@@Error: push ax
mov ah,9
int 21h
pop ax
mov ah,4Ch
int 21h ; terminate
Stub4GW ENDP
;*** Check presence of 386 or better processor
; In: none
; Out: AL=0, CF=NC - 386 found
; AL!=0, CF=CY - no 386
; Changes: AH
Check386 PROC
pushf
mov ax,7000h
push ax
popf
pushf
pop ax
and ax,07000h
jz @@1 ; not found
mov al,1 ; found 386
@@1: popf
sub al,1
ret
Check386 ENDP
.386
;*** Shrink memory block used by the loader
ReleaseMemory PROC
USES ES,BX
mov bx,ss ; Stack segment - end of pgm
add bx,(StackSize+15)/16
mov ax,fs ; PSP segment - start of pgm
sub bx,ax
mov es,ax
mov ah,4Ah
int 21h
ret
ReleaseMemory ENDP
;*** Find DOS4GW.EXE or DOS4G.EXE
; In: none
; Out: DS:DX DOS4G[W] full path (if possible)
; Changes: AX
FindDOS4GW PROC
; Try DOS4GPATH
mov dx,offset EnvDOS4GPATH
call FindProgram
jnc @@Ret
; Try PATH
mov dx,offset EnvPATH
call FindProgram
jnc @@Ret
; none found -- return current directory
mov dx,offset DOS4GW_EXE
@@Ret: ret
FindDOS4GW ENDP
;*** Find DOS4GW.EXE or DOS4G.EXE using environment variable
; In: DS:DX Environment variable name
; Out: CF=NC found
; CF=CY not found
; DS:DX DOS4G[W] full path
; Changes: AX
FindProgram PROC
USES SI,DI,BX
; Read environment
mov di,offset EnvBuffer
call GetEnv
cmp ax,0
jb @@Ret
; Variable exists
mov si,di
mov di,offset DOS4GWpathName
mov bx,offset DOS4GW_EXE
call ScanPath
jnc @@Ret
mov bx,offset DOS4G_EXE
call ScanPath
@@Ret: ret
FindProgram ENDP
;*** Get environment string
; In: DS:DX environment variable name (must be uppercase) LString
; ES:DI destination buffer
; GS:0000 environment
; Out: AX = -1 not found
; otherwise AX contains length
; [ES:DI] filled
GetEnv PROC
USES SI,DI,BX,CX
cld
mov si,dx
lodsb
movzx cx,al
jcxz @@NotFound
;
mov bx,-1 ; GS:BX - environment pointer
@@Scan: push cx si
@@1: lodsb
inc bx
cmp al,gs:[bx]
loope @@1
pop si cx
jne @@Next
inc bx
cmp BYTE PTR gs:[bx],'='
jne @@Next
; found -- copy it to ES:DI
lea cx,[bx+1]
@@2: inc bx
mov al,gs:[bx]
stosb
or al,al
jnz @@2
mov ax,bx
sub ax,cx
jmp @@Ret
; skip to next
@@Next: xor al,al
@@3: inc bx
cmp gs:[bx],al
jnz @@3
cmp gs:[bx+1],al
jnz @@Scan
; variable not found
@@NotFound: mov ax,-1
@@Ret: ret
GetEnv ENDP
;*** Get program path from the environment
; In: ES:DI destination buffer
; GS:0000 environment
; Out: CX length
; [ES:DI] filled
GetPgmPath PROC
USES BX
cld
xor bx,bx ; GS:BX - environment pointer
xor ax,ax
mov cx,8000h
@@1: cmp gs:[bx],ax
je @@2
inc bx
loop @@1
jmp @@Ret ; not found - this should never happen
; found -- copy it to ES:DI
@@2: add bx,4 ; skip zeros and count (1)
xor cx,cx ; CX - count
@@3: mov al,gs:[bx]
inc bx
inc cx
stosb
or al,al
jnz @@3
dec cx ; CX=length of the pathname
@@Ret: ret
GetPgmPath ENDP
;*** Scan directories specified in form 'path1;path2;path3...' for filename
; In: DS:BX filename to be found
; DS:SI path
; ES:DI destination buffer for full filename
; Out: CF=NC, AX=0 found
; CF=CY, AX!=0 not found
; ES:DX = ES:DI full filename
ScanPath PROC
USES BX,CX
cld
mov dx,di
@@Loop: xor ax,ax
; copy one element of path
@@1: lodsb
cmp al,';'
je @@2
or al,al
je @@2
stosb
inc ah
jmp @@1
; add backslash if necessary
@@2: mov cx,ax ; save last char
or ah,ah
jz @@3 ; AH=0 -- path element is empty
mov al,es:[di-1]
cmp al,'\'
je @@3
cmp al,':'
je @@3
mov al,'\' ; append backslash
stosb
; add filename to path
@@3: push si
mov si,bx
@@4: lodsb
stosb
or al,al
jnz @@4
pop si
; DS:DX now contains full path
mov ax,3D40h ; open for reading, deny none
int 21h
jc @@5 ; error -- file not found
; file exists, close its handle
mov bx,ax
mov ah,3Eh
int 21h
xor ax,ax
jmp @@Ret
;
@@5: mov di,dx ; DX=saved DI
or cl,cl ; CL=last char (00h or ';')
jnz @@Loop
stc
@@Ret: ret
ScanPath ENDP
;*** Prepare program parameters
; In: none
; Out: ES:BX parameters
; Changes: AX
PrepareParams PROC
USES SI,DI,CX
mov di,offset EnvBuffer+1
call GetPgmPath
dec di
; add space if necessary
mov si,PSP_PARAMS
lods BYTE PTR fs:[si]
xor ah,ah ; AX=length of orig. params
or ax,ax
jz @@1
push ax
mov al,' '
cmp BYTE PTR fs:[si],al
je @@0
stosb
inc cx
@@0: pop ax
; add original parameters
@@1: mov bx,7Eh ; max. length of parameters
sub bx,cx
xchg bx,cx ; BX=length so far
cmp cx,ax ; CX=remaining bytes
jbe @@2
mov cx,ax ; CX=bytes to be copied
@@2: add bx,cx ; BX=total length
inc cx ; copy trailing CR
rep movs BYTE PTR es:[di], fs:[si]
;
mov al,bl
mov bx,offset EnvBuffer
mov [bx],al
ret
PrepareParams ENDP
IFDEF QUIET
;*** Prepare program environment -- add string "DOS4G=QUIET"
; In: GS:0000 environment
; Out: AX new environment segment
PrepareEnvironment PROC
USES ES,BX,DI
mov ax,gs
dec ax
mov es,ax
mov bx,es:[3] ; size of current environment
shl bx,4
;
inc ax
mov es,ax
xor ax,ax
xor di,di
@@1: cmp es:[di],al
je @@2
mov cx,8000H
repne scasb
jmp @@1
;
@@2: mov ax,bx
sub ax,di
cmp ax,EnvDOS4G_Len+5
jge @@3
; create new environment block
lea bx,[di+EnvDOS4G_Len+5+15]
shr bx,4
mov ah,48h ; allocate memory
int 21h
jc @@Ret
push si
mov es,ax ; ES - new environment segment
mov cx,di ; GS - old environment segment
xor di,di
xor si,si
rep movs BYTE PTR es:[di], gs:[si]
pop si
mov bx,gs
mov gs,ax ; GS - new environment segment
mov fs:[Environment],ax ; update environment segment #
push es
mov es,bx
mov ah,49H ; free old environment block
int 21h
pop es
; add string (destroying program load path)
@@3: mov si,offset EnvDOS4G
mov cx,EnvDOS4G_Len
rep movsb
xor ax,ax
stosb
stosw
stosw
@@Ret: mov ax,gs
ret
PrepareEnvironment ENDP
ENDIF
;*** Run program
; In: DS:DX complete filename (ASCIIZ)
; ES:BX parameters
; AX environment segment
; Out: AX exec code
Exec PROC
; Prepare environment
mov EPB_Env,ax
; Prepare Parameters
mov EPB_Param.Ofst,bx
mov EPB_Param.Segm,es
; Prepare FCBs
mov EPB_FCB1.Ofst,FCB1
mov EPB_FCB1.Segm,fs ; FS=PSP
mov EPB_FCB2.Ofst,FCB2
mov EPB_FCB2.Segm,fs
; Save stack
mov SaveStack.Ofst,sp
mov SaveStack.Segm,ss
; Execute
mov bx,offset EPB
mov ax,4B00h
int 21h
; Restore stack & segments
cli
jc @@1
xor ax,ax
@@1: mov bx,cs
mov ds,bx
mov es,bx
lss sp,SaveStack
sti
cld
ret
Exec ENDP
;*** Convert 16-bit register to 4 hex digits
; In: AX number
; DS:BX destination
; Out: DS:BX end of string
; Changes: AX, BX
HexWord PROC
push ax
mov al,ah
call HexByte
pop ax
HexByte PROC ; AL --> Hex Ascii DS:BX
push ax
shr al,4
call @@1
pop ax
and al,0fh
@@1: add al,90h
daa
adc al,40h
daa
mov [bx],ax
inc bx
ret
HexByte ENDP
HexWord ENDP
;; db 3 dup (0) ; align manually
.DATA
Msg_Need386 db 'This program requires 386 or better processor',CRLF,EOL
Msg_Error db 'Can''t run DOS4GW.EXE. Error code '
Msg_ErrorCode db '0000',CRLF,EOL
EnvDOS4GPATH db 9,'DOS4GPATH'
EnvPATH db 4,'PATH'
db 0
DOS4GW_EXE db 'DOS4GW.EXE',0
DOS4G_EXE db 'DOS4G.EXE',0
IFDEF QUIET
EnvDOS4G db 'DOS4G=QUIET',0
EnvDOS4G_Len = $ - EnvDOS4G
ENDIF
; align the file-length to be a multiple of 16
IFDEF QUIET
db 9 dup (0)
ELSE
db 13 dup (0)
ENDIF
.DATA?
SaveStack dd ?
EPB LABEL BYTE ; EPB - Exec parameter block
EPB_Env dw ?
EPB_Param dd ?
EPB_FCB1 dd ?
EPB_FCB2 dd ?
DOS4GWpathName db 128 dup (?)
EnvBuffer db 128 dup (?)
.STACK StackSize
END Stub4GW